<template>
  <view class="gg-tab-lists">
    <!-- tab按钮 -->
    <view class="gg-tab-lists-tab-area" v-if="disableTab==false">
      <scroll-view class="gg-tab-lists-tab-box" scroll-x="true" :scroll-left="localTabScrollLeft" :show-scrollbar="false" scroll-with-animation
        @scroll="onTabScroll">
        <view class="gg-tab-lists-tab-item" v-bind:style="tabItemStyle" v-for="(item,index) in localTabLists" :key="index"
          :class="'gg-tab-lists-tab-item-id-'+(index+1)">
          <view class="gg-tab-lists-tab-item-area" @tap="changeTab(index)" :key="index">
            <view class="gg-tab-lists-tab-item-area-title-box">
              <view class="gg-tab-lists-tab-item-area-title-item">
                {{item.tabTitle}}
                <view class="gg-tab-lists-tab-item-area-title-orderby" v-if="item.orderby">
                  <view class="gg-tab-lists-tab-item-area-title-asc">
                    <view class="gg-tab-lists-tab-item-area-title-asc-item"
                      :class="item.ordersort=='ASC'&&localTabIndex==index?'gg-tab-lists-tab-item-area-title-asc-selected':''">
                    </view>
                  </view>
                  <view class="gg-tab-lists-tab-item-area-title-desc">
                    <view class="gg-tab-lists-tab-item-area-title-desc-item"
                      :class="item.ordersort=='DESC'&&localTabIndex==index?'gg-tab-lists-tab-item-area-title-desc-selected':''">
                    </view>
                  </view>
                </view>
              </view>
            </view>
            <view class="gg-tab-lists-tab-item-area-border" :class="localTabIndex==index?'gg-tab-lists-tab-item-area-border-checked':''">
            </view>
          </view>
        </view>
      </scroll-view>
    </view>
    <view class="gg-tab-lists-data-area" :style="disableTab==true?'height:100%;':''">
      <swiper class="gg-tab-lists-data-swiper" :current="localTabIndex" @change="changeSwiper" @animationfinish="onAnimationfinish"
        @transition="onTransition" :disableTouch="disableTouch">
        <swiper-item v-for="(item,index) in localTabLists" :key="index" :show-scrollbar="true">
          <scroll-view class="gg-tab-lists-data-scroll-box" scroll-y="true"
            :refresher-enabled="localTabLists[index].enabled && disableEnabled===false" refresher-background="#eeeeee"
            :refresher-triggered="localTabLists[index].triggered" @scrolltolower="onTolower(index)" @scrolltoupper="onToupper" @scroll="onScroll"
            @refresherrefresh="onRefresh" @refresherrestore="onRestore" @refresherabort="onAbort">
            <view v-if="localDataLists[index].data.length > 0" :class="listsClass">
              <view v-for="(rows,i) in localDataLists[index].data" :key="i" style="display: contents !important;">
                <slot :rows="rows" :index="i" :tabIndex="index" />
              </view>
            </view>
            <view class="gg-tab-lists-data-scroll-box-nodata-msg"
              v-if="localTabLists[index].loadMoreStatus =='noMore' && localDataLists[index].data.length <=0 && localTabLists[index].nodataMsg">
              {{localTabLists[index].nodataMsg}}
            </view>
            <gg-load-more :status="localTabLists[index].loadMoreStatus" @clickLoadMore="onTolower(index)" :contentText="loadMoreText" v-else />
          </scroll-view>
        </swiper-item>
      </swiper>
    </view>
  </view>
</template>
<script>
export default {
  name: 'GgTabLists',
  props: {
    tabsConfig: {
      type: [Array, Function],
      default() {
        return [];
      }
    },
    /* 是否禁止左右滑动切换 */
    disableTouch: {
      type: Boolean,
      default() {
        return false;
      }
    },
    /* 是否禁止显示tab */
    disableTab: {
      type: Boolean,
      default() {
        return false;
      }
    },
    /* 是否禁止下拉刷新 */
    disableEnabled: {
      type: Boolean,
      default() {
        return false;
      }
    },
    /* 监听更新数据通知 ,接收时间戳 */
    onUpdate: {
      type: Number,
      default() {
        return 0;
      }
    },
    listsClass: {
      type: String,
      default() {
        return '';
      }
    },
    /* 接口公共参数 */
    publicParam: {
      type: Object,
      default() {
        return {};
      }
    },
    publicFunc: {
      type: Function,
      default() {
        return null;
      }
    },
    tabIndex: {
      type: Number,
      default() {
        return 0;
      }
    }
  },
  data() {
    return {
      localTabLists: [],
      localTabIndex: 0,
      localDataLists: [],
      scrollTop: 0,//当前列顶部位置
      triggered: false,
      tabItemStyle: '',
      windowWidth: 414,
      localTabScrollLeft: 0,
      tabScrollLeft: 0,
      loadMoreText: { contentdown: "上拉或点击显示更多", contentrefresh: "正在加载...", contentnomore: "没有更多数据了" }
    }
  },
  watch: {
    tabsConfig: {
      deep: true, //深度监听设置为 true
      handler: function (newV, oldV) {
        this._dealtabsConfig();
      }
    },
    localDataLists(newArr) {
      // console.log('监听localDataLists的变动');
    },
    localTabIndex(newArr) {
      // console.log('监听localTabIndex的变动');
    },
    onUpdate(newArr) {
      //重置所有数据
      //console.log('监听onUpdate', this.onUpdate)
      this._dealtabsConfig();
    },
    publicParam: {
      deep: true, //深度监听设置为 true
      handler: function (newV) {
        this._dealtabsConfig();
      }
    }
  },
  created() {
    uni.getSystemInfo({
      success: (res) => {
        this.windowWidth = res.windowWidth
      }
    });
  },
  mounted() {
    this._dealtabsConfig();
  },
  methods: {
    _dealtabsConfig() {
      let localTabLists = [];
      let localDataLists = [];
      for (const key in this.tabsConfig) {
        localTabLists.push({ ...this.tabsConfig[key] });
        localTabLists[key].enabled = true; //开启自定义下拉刷新
        localTabLists[key].loadMoreStatus = 'more';//gg-load-more 组件 status 状态
        localTabLists[key].scrollTop = 0;
        localTabLists[key].ordersort = this.tabsConfig[key].ordersort == 'DESC' ? 'DESC' : 'ASC';//默认倒叙
        localTabLists[key].pagesize = this.tabsConfig[key].pagesize || 10;//页长
        localDataLists[key] = {
          page: 1,
          data: []
        }
      }
      this.localTabLists = localTabLists;
      this.localDataLists = localDataLists;
      this.localTabIndex = this.localTabIndex || this.tabIndex;

      if (localTabLists.length > 0 && this.disableTab === false) {
        this._dealTabWidth(localTabLists);
      }
      this.getData();
    },
    /* 设置tab宽度 */
    _dealTabWidth(localTabLists) {
      let tabItemWidth = 0,
        tabWidth = 0,
        tabItemStyle = '';
      /* #ifdef APP-PLUS */
      let query = uni.createSelectorQuery().in(this);
      for (var i = 1; i <= localTabLists.length; ++i) {
        query.select('.gg-tab-lists-tab-item-id-' + i).boundingClientRect((data) => {
          tabItemWidth += 40
          if (data) {
            tabItemWidth += data.width
          }
        }).exec();
      }
      query.select('.gg-tab-lists-tab-box').boundingClientRect((data) => {
        tabWidth = data.width
        /* 写在这里面是为了兼容微信小程序，如果写在外面这句会先执行 */
        if (tabItemWidth <= tabWidth) {
          tabItemStyle += 'width:calc(100% / ' + localTabLists.length + ' - 40px);';
        }
        tabItemStyle += 'top:0;';
        this.tabItemStyle = tabItemStyle;
        this.$forceUpdate();
      }).exec();
      /* #endif */
      /* #ifndef APP-PLUS */
      setTimeout(() => {
        for (var i = 1; i <= localTabLists.length; ++i) {
          uni.createSelectorQuery().in(this).select('.gg-tab-lists-tab-item-id-' + i).boundingClientRect((data) => {
            tabItemWidth += 40
            if (data) {
              tabItemWidth += data.width
            }
          }).exec();
        }
        uni.createSelectorQuery().in(this).select('.gg-tab-lists-tab-box').boundingClientRect((data) => {
          tabWidth = data.width
          /* 写在这里面是为了兼容微信小程序，如果写在外面这句会先执行 */
          if (tabItemWidth <= tabWidth) {
            tabItemStyle += 'width:calc(100% / ' + localTabLists.length + ' - 40px);';
          }
          tabItemStyle += 'top:0;';
          this.tabItemStyle = tabItemStyle;
          this.$forceUpdate();
        }).exec();
      }, 0)
      /* #endif */
    },
    /* 处理滚动条距离左边的距离 */
    _dealTabScrollLeft() {
      if (this.disableTab == true) {
        return;
      }
      const i = this.localTabIndex + 1,
        windowWidth = this.windowWidth;
      let tabLeft = 0,
        localTabScrollLeft = this.tabScrollLeft,
        tabWidth = 0
      uni.createSelectorQuery().in(this).select('.gg-tab-lists-tab-item-id-' + i).boundingClientRect(data => {
        tabLeft = data.left - 20;
        tabWidth = data.width + 40
        localTabScrollLeft += tabLeft - (windowWidth / 2) + tabWidth / 2
        this.localTabScrollLeft = localTabScrollLeft;
      }).exec();
    },
    onTabScroll(e) {
      this.tabScrollLeft = e.detail.scrollLeft
    },
    changeTab(e) {
      if (e != this.localTabIndex) {
        this.localTabIndex = e;
      } else {
        // console.log('点击当前页Tab 判断是否支持排序切换');
        if (this.localTabLists[e].loadMoreStatus == 'loading') {
          console.warn('请不要点这么快，上次请求还没结束呢');
          return;
        }
        if (this.localTabLists[e].orderby) {
          //console.warn('支持排序的Tab哦');
          if (this.localTabLists[e].ordersort == 'DESC') {
            this.localTabLists[e].ordersort = 'ASC'
            //console.warn(this.localTabLists[e].orderby, '排序改为：', this.localTabLists[e].ordersort,)
          } else {
            this.localTabLists[e].ordersort = 'DESC'
            //console.warn(this.localTabLists[e].orderby, '排序改为：', this.localTabLists[e].ordersort)
          }
          // console.log('重置当前列数据重新发起请求');
          this.$set(this.localDataLists[e], 'page', 1);
          this.$set(this.localDataLists[e], 'data', []);
          this.$forceUpdate();
          this.getData();
        }
      }
    },
    changeSwiper(e) {
      // console.log('changeSwiper 监听Swiper变化', e.detail.current);
      let current = e.detail.current;
      this.localTabIndex = current;
      this.$emit('change', this.localTabIndex);
      if (this.localDataLists[current].data.length <= 0) {
        // console.log('第一次打开此区初始化数据');
        this.getData();
      }
      this._dealTabScrollLeft()
      this.$set(this.localTabLists[current], 'enabled', true)
    },
    getData() {
      const localTabLists = this.localTabLists;//Tab数组
      const localTabIndex = this.localTabIndex;//当前区域坐标
      const localDataLists = this.localDataLists;//滑块缓存数据
      if (localTabLists.length <= 0) {
        console.warn('localTabLists 参数为有误');
        return;
      }
      this.localTabLists[localTabIndex].loadMoreStatus = 'loading'
      let apiUrl = localTabLists[localTabIndex].apiUrl;
      let page = 1;
      if (localDataLists[localTabIndex]) {
        page = localDataLists[localTabIndex].page
      }
      let apiParam = {
        pagesize: localTabLists[localTabIndex].pagesize,
        page: page
      };
      apiParam = Object.assign(apiParam, this.publicParam);//公共参数
      apiParam = Object.assign(apiParam, localTabLists[localTabIndex].apiParam);//当前列参数
      //排序字段
      if (localTabLists[localTabIndex].orderby) {
        apiParam[localTabLists[localTabIndex].orderby] = localTabLists[localTabIndex].ordersort
      }
      // console.warn('apiParam', apiParam)
      if (localTabLists[localTabIndex].apiFunc) {
        //使用私有方法请求
        localTabLists[localTabIndex].apiFunc(apiParam).then((successRes) => {
          this.dealDataList(successRes.data, localTabIndex, page);
        }).catch((error) => {
          this.dealDataList([], localTabIndex, page);
          // console.log('error', error);
        });
      } else if (this.publicFunc) {
        /* 使用公共方法请求 */
        if (localTabLists[localTabIndex].apiFlag) {
          //有标识
          this.publicFunc(localTabLists[localTabIndex].apiFlag, apiParam).then((successRes) => {
            this.dealDataList(successRes.data, localTabIndex, page);
          }).catch((error) => {
            this.dealDataList([], localTabIndex, page);
            // console.log('error', error);
          });
        } else {
          //无标识
          this.publicFunc(apiParam).then((successRes) => {
            this.dealDataList(successRes.data, localTabIndex, page);
          }).catch((error) => {
            this.dealDataList([], localTabIndex, page);
            // console.log('error', error);
          });
        }

      } else if (localTabLists[localTabIndex].apiUrl) {
        console.warn('拿到apiUrl 开始请求,此处代码不全')

      } else {
        //console.warn('参数有误：apiFunc、apiUrl  至少有一个不为空');
        setTimeout(() => {
          this.localTabLists[localTabIndex].triggered = false;
          //console.log('请求结束，关闭下拉刷新状态', this.localTabLists[this.localTabIndex].enabled, this.localTabLists[this.localTabIndex].triggered)
          this.localTabLists[localTabIndex].loadMoreStatus = 'noMore';
          this.$forceUpdate();
          setTimeout(() => {
            this.localTabLists[localTabIndex].triggered = 'restore';
            //console.log('需要重置===========下啦状态')
            this.$forceUpdate();
          }, 10)
        }, 3000)
      }
    },
    /* 整理列表数据 */
    dealDataList(data = [], index, page = 0) {
      let dataLists = [];
      if (!data || data.length <= 0) {
        //没有更多数据了
        this.localTabLists[index].loadMoreStatus = 'noMore';
        this.$forceUpdate();
      } else {
        /* 判断父级是否有解析数据要求 */
        if (this.localTabLists[index].parseFunc) {
          data = this.localTabLists[index].parseFunc(data);
        }
        if (this.localDataLists[index]) {
          dataLists = [...this.localDataLists[index].data]
        }
        for (const key in data) {
          dataLists.push(data[key]);
        }
        this.$set(this.localDataLists[index], 'data', dataLists)
        this.$set(this.localDataLists[index], 'page', page + 1)
        this.$forceUpdate();
        if (data.length < this.localTabLists[index].pagesize) {
          this.localTabLists[index].loadMoreStatus = 'noMore';
        } else {
          this.localTabLists[index].loadMoreStatus = 'more';
        }
      }
      this.$emit('dataLists', { tabIndex: index, data: dataLists });
      if (this.localTabLists[index].triggered == true) {
        // console.log('关闭下拉刷新状态');
        setTimeout(() => {
          this.localTabLists[index].triggered = false;
          this.$forceUpdate();
        }, 100)
      }
      this.$forceUpdate();

    },
    /* swiper-item 的位置发生改变时会触发 transition 事件，event.detail = {dx: dx, dy: dy}，支付宝小程序暂不支持dx, dy */
    onTransition(e) {
      if (this.localTabLists[this.localTabIndex].enabled !== false) {
        // console.log('swiper-item 左右滑动时 锁定‘scroll-view’下拉刷新功能', e)
        this.$set(this.localTabLists[this.localTabIndex], 'enabled', false)
      }

    },
    /* 动画结束时会触发 animationfinish 事件，event.detail = {current: current, source: source} */
    onAnimationfinish(e) {
      if (this.localTabLists[this.localTabIndex].enabled !== true && this.localTabLists[this.localTabIndex].scrollTop < 45) {
        // console.log('swiper-item 动画结束时 开启‘scroll-view’下拉刷新功能', e)
        this.$set(this.localTabLists[this.localTabIndex], 'enabled', true)
      }
    },
    onScroll(e) {
      const scrollTop = e.detail.scrollTop;
      this.localTabLists[this.localTabIndex].scrollTop = scrollTop;
      if (scrollTop == 0 && this.localTabLists[this.localTabIndex].enabled != true) {
        // this.localTabLists[this.localTabIndex].enabled = true;
        this.$forceUpdate();
        // console.log('---滑到顶部了 可以开启下拉刷新了', this.localTabLists[this.localTabIndex].enabled);
      } else if (scrollTop > 0 && this.localTabLists[this.localTabIndex].enabled != false) {
        this.$set(this.localTabLists[this.localTabIndex], 'enabled', false)
        // console.log('---没在顶部 必须禁止下拉刷新了', this.localTabLists[this.localTabIndex].enabled);
      }
    },
    /* 监听回到顶部 */
    onToupper(e) {
      // console.log('监听回到顶部', e);
      this.$set(this.localTabLists[this.localTabIndex], 'enabled', true)
    },
    /* 监听触底 */
    onTolower(e) {
      // console.log('滚到底部咯', e)
      switch (this.localTabLists[e].loadMoreStatus) {
        case 'noMore':
          console.warn('没有更多了哦', e);
          break;
        case 'loading':
          console.warn('当前列上一次请求还未结束，请稍后', e);
          break;
        default:
          this.getData();
      }
    },
    /* 自定义下拉刷新被触发 */
    onRefresh() {
      console.warn('自定义下拉刷新被触发咯========');
      if (this.localTabLists[this.localTabIndex].loadMoreStatus == 'loading') {
        console.warn('当前列上一次请求还未结束，请稍后');
        return;
      }
      if (this.localTabLists[this.localTabIndex].triggered == true) {
        // console.log('正在处理下拉刷新业务，因此终止此次触发-----一般情况不会走到这里')
        return;
      }
      // console.log('重置当前列数据');
      this.$set(this.localTabLists[this.localTabIndex], 'triggered', true);
      this.$set(this.localDataLists[this.localTabIndex], 'page', 1);
      this.$set(this.localDataLists[this.localTabIndex], 'data', []);
      this.$forceUpdate();
      this.getData();
    },
    /* 自定义下拉刷新被复位 */
    onRestore() {
      // console.log('自定义下拉刷新被复位 【onRestore】');
      //this.localTabLists[this.localTabIndex].triggered = 'restore';
    },
    /* 自定义下拉刷新被中止	 */
    onAbort(e) {
      // console.log('自定义下拉刷新被中止,中止后默认开启下拉刷新，****此处代码运行效率低需要优化****	');
      //检测是否因满足开启下拉刷新而未开启
      if (this.localTabLists[this.localTabIndex].enabled !== true) {
        // this.$set(this.localTabLists[this.localTabIndex], 'enabled', true)
      }

    },
    testReqMocck(testData) {
      return new Promise((resolve, reject) => {
        resolve({
        });
      });
    }
  }
};
</script>
<style>
/* #ifdef MP-WEIXIN */
gg-tab-lists {
  position: relative;
  display: block;
}
/* #endif */
.gg-tab-lists {
  position: absolute;
  height: 100%;
  overflow: auto;
  width: 100%;
}
.gg-tab-lists-tab-area {
  height: 40px;
  background: #ffffff;
  border-bottom: solid 1px rgba(0, 0, 0, 0.1);
}
.gg-tab-lists-tab-area::-webkit-scrollbar {
  display: none; /* Chrome Safari */
}
.gg-tab-lists-tab-box {
  width: 100%;
  height: 40px;
  white-space: nowrap;
  font-size: 0;
}
.gg-tab-lists-tab-item {
  display: inline-block;
  width: auto;
  height: 40px;
  margin: 0 20px;
  /* transition: all 0.4s; */
  position: relative;
  top: 40px;
}
.gg-tab-lists-tab-item-area-title-box {
  font-size: 14px;
  padding: 8px 0;
  display: flex;
  height: 20px;
  box-sizing: unset;
}
.gg-tab-lists-data-scroll-box-nodata-msg {
  height: 40px;
  line-height: 40px;
  font-size: 15px;
  color: #999999;
  text-align: center;
}
.gg-tab-lists-tab-item-area-title-item {
  margin: auto;
  position: relative;
}
.gg-tab-lists-tab-item-area-title-orderby {
  height: 20px;
  position: absolute;
  top: 0;
  right: -17px;
}
.gg-tab-lists-tab-item-area-title-asc,
.gg-tab-lists-tab-item-area-title-desc {
  height: 6px;
  width: 12px;
}
.gg-tab-lists-tab-item-area-title-asc {
  margin-top: -3px;
}
.gg-tab-lists-tab-item-area-title-asc-item {
  transition: all 0.2s;
  width: 0;
  height: 0;
  border-width: 6px;
  border-style: solid;
  border-top-color: transparent;
  border-right-color: transparent;
  border-bottom-color: #dedede;
  border-left-color: transparent;
}
.gg-tab-lists-tab-item-area-title-asc-selected {
  border-bottom-color: #ff5400;
}
.gg-tab-lists-tab-item-area-title-desc {
  margin-top: 8px;
}
.gg-tab-lists-tab-item-area-title-desc-item {
  transition: all 0.2s;
  width: 0;
  height: 0;
  border-width: 6px;
  border-style: solid;
  border-top-color: #dedede;
  border-right-color: transparent;
  border-bottom-color: transparent;
  border-left-color: transparent;
}
.gg-tab-lists-tab-item-area-title-desc-selected {
  border-top-color: #ff5400;
}
.gg-tab-lists-tab-item-area-border {
  height: 2px;
  background-color: #ffffff;
  border-radius: 2px;
  margin: 0 1px;
  transition: all 0.2s;
}
.gg-tab-lists-tab-item-area-border-checked {
  background-color: #ff5400;
}
.gg-tab-lists-data-area {
  height: calc(100% - 40px - 1px);
}
.gg-tab-lists-data-swiper {
  height: 100%;
}
.gg-tab-lists-data-scroll-box {
  height: 100%;
}
</style>
